package cn.mall.user.service.impl;

import cn.mall.base.constants.BaseConstants;
import cn.mall.base.constants.BasicMap;
import cn.mall.base.utils.AjaxResult;
import cn.mall.base.utils.MD5Utils;
import cn.mall.bill.domain.Bill;
import cn.mall.bill.mapper.BillMapper;
import cn.mall.user.domain.User;
import cn.mall.user.dto.LoginDTO;
import cn.mall.user.dto.RechargeDTO;
import cn.mall.user.dto.RegisterDTO;
import cn.mall.user.mapper.UserMapper;
import cn.mall.user.service.IUserService;
import cn.mall.base.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Jarvis-Smith
 * @since 2023-11-30
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private BillMapper billMapper;





    @Override
    public AjaxResult insertU(User user) {
        //密码加密
        //生成随机字符串盐值
        User user1 = userMapper.loadByUsername(user.getUsername());
        if(user1 != null){
           return  AjaxResult.me().setSuccess(false).setMessage("用户名已存在,请修改用户名!");
        }
        String salt = UUID.randomUUID().toString();
        String md5Password = MD5Utils.encrypByMd5(salt + user.getPassword() + "user");
        user.setPassword(md5Password);
        user.setSalt(salt);
        user.setCreatetime(new Date());
        user.setDisable(BaseConstants.AccountDisable.ACCOUNTABLE);
        user.setBalance(BigDecimal.ZERO);
        userMapper.insert(user);
        return AjaxResult.me();
    }


    @Override
    @Transactional
    public AjaxResult updateU(User user) {
        User user1 = userMapper.loadById(user.getId());
        user.setToken(user1.getToken());
        if (!user1.getPassword().equals(user.getPassword())){
            //密码加密
            //生成随机字符串盐值
            String token = user1.getToken();
            if(token != null){
                Object o = redisTemplate.opsForValue().get(token);
                if(o != null){
                    redisTemplate.delete(token);
                }
            }
            String md5Password = MD5Utils.encrypByMd5(user.getSalt() + user.getPassword() + "user");
            user.setPassword(md5Password);
        }
        userMapper.update(user);
        return AjaxResult.me();
    }

    @Override
    public Float getBalaceAll() {
        return userMapper.getBalaceAll();
    }

    @Override
    public void userRegister(RegisterDTO dto) {
        //参数非空校验
        ParameterNonnullCheck(dto);

        //密码加密
        //生成随机字符串盐值
        String salt = UUID.randomUUID().toString();
        String md5Password = MD5Utils.encrypByMd5(salt + dto.getPassword() + "user");

        //将信息存入User表
        User user = new User();
        user.setUsername(dto.getUsername());
        user.setPassword(md5Password);
        user.setEmail(dto.getEmail());
        user.setPhone(dto.getPhone());
        user.setSalt(salt);
        user.setCreatetime(new Date());
        user.setDisable(BaseConstants.AccountDisable.ACCOUNTABLE);
        user.setBalance(BigDecimal.ZERO);
        userMapper.insert(user);

    }

    /**
     * 用户登录
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> loginIn(LoginDTO dto) {
        // 判断用户名是否为空
        if (StringUtils.isEmpty(dto.getUsername()) || StringUtils.isEmpty(dto.getPassword())) {
            throw new RuntimeException("用户名或密码不能为空");
        }
        //根据用户名查询用户信息
        User user = userMapper.loadByUsername(dto.getUsername());
        if (Objects.isNull(user)) {
            throw new RuntimeException("用户名或密码错误");
        }
        // 校验用户名的密码是否正确
        String md5Password = MD5Utils.encrypByMd5(user.getSalt() + dto.getPassword() + "user");

        if (!md5Password.equals(user.getPassword())) {
            throw new RuntimeException("用户名或密码错误");
        }
        Map<String, Object> userMap= new HashMap<>();
        if(user.getToken()!= null){
            // 此情况 已登录过 直接覆盖
            Object o = redisTemplate.opsForValue().get(user.getToken());
            if(o!=null){
                redisTemplate.delete(user.getToken());
            }

        }

        // 使用UUID生成token
        String s = UUID.randomUUID().toString();
        String token = MD5Utils.encrypByMd5(user.getUsername()+s);
        User user1 = userMapper.loadById(user.getId());
        user1.setToken(token);
        // 将用户信息存到 redis中
        redisTemplate.opsForValue().set(token, user, 6, TimeUnit.HOURS);
        userMapper.update(user1);
        // 登录成功，返回map信息给前端
        user.setPassword("");
        user.setSalt("");

        userMap.put("token", token);
        userMap.put("loginUser", user);

        // 返回map
        return userMap;
    }

    /**
     * 用户余额充值
     * @param rechargeDTO
     */
    @Override
    @Transactional
    public void balanceRecharge(RechargeDTO rechargeDTO) {
        // 参数非空校验校验
        if (StringUtils.isEmpty(rechargeDTO.getId())) {
            throw new RuntimeException("用户 id 不能为空");
        }
        // 查找是否有该用户
        User user = userMapper.loadById(rechargeDTO.getId());
        if (Objects.isNull(user)) {
            throw new RuntimeException("用户不存在");
        }
        // 更改金额
        user.setBalance(user.getBalance().add(rechargeDTO.getBalance()));
        userMapper.update(user);
        User user1 = userMapper.loadById(user.getId());
        //增加消费记录 消费类型 1充值
        Bill bill = new Bill();
        bill.setType(1);
        bill.setBtype(1);
        bill.setMoney(rechargeDTO.getBalance());
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = sdf.format(date);
        bill.setTime(formattedDate);
        bill.setUserid(user.getId());
        bill.setBalance(user1.getBalance());
        billMapper.insert(bill);

    }

    /**
     * 参数非空校验
     * @param dto
     */
    public void ParameterNonnullCheck(RegisterDTO dto) {
        // 所有参数的非空校验
        if (StringUtils.isEmpty(dto.getPhone()) || StringUtils.isEmpty(dto.getEmail()) || StringUtils.isEmpty(dto.getUsername()) || StringUtils.isEmpty(dto.getPassword()) || StringUtils.isEmpty(dto.getConfirmPassword())) {
            throw new RuntimeException("请填写所有信息");
        }
        // 用户名查重
        User user = userMapper.loadByUsername(dto.getUsername());
        if (Objects.nonNull(user)) {
            throw new RuntimeException("用户名已存在，请重新输入");
        }
        // 两次密码验证
        if (!dto.getPassword().trim().equals(dto.getConfirmPassword().trim())) {
            throw new RuntimeException("两次密码不一致，请重新输入");
        }
    }
}
